//
// OpenTemplate
// Copyright (c) 2006
// by OpenArrow Software ( http://www.openarrow.com )
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections.Generic;
using System.Text;
using OpenArrow.Templating.Parsing;
using OpenArrow.Templating.Compilation;
using OpenArrow.Templating.Properties;

namespace OpenArrow.Templating
{
    /// <summary>
    /// Represents the results of processing a group of templates
    /// </summary>
    public class ProcessorResults
    {
        private Dictionary<string, IndividualProcessorResults> results = new Dictionary<string, IndividualProcessorResults>();
        private ProblemCollection generalProblems = new ProblemCollection();

        /// <summary>
        /// Gets or sets a boolean determining if all files were successfully processed
        /// </summary>
        public bool Success
        {
            get { 
                bool success = true;
                foreach(IndividualProcessorResults result in results.Values)
                    success &= result.Success;
                return success;
            }
        }
        
        /// <summary>
        /// Gets a dictionary where the key represents the file and the value represents
        /// the results of processing that file
        /// </summary>
        public Dictionary<string, IndividualProcessorResults> IndividualResults
        {
            get { return results; }
        }

        /// <summary>
        /// Gets a collection of general problems that occurred during processing
        /// </summary>
        public ProblemCollection GeneralProblems
        {
            get { return generalProblems; }
        }
    }

    /// <summary>
    /// Represents the results of processing a single file
    /// <see cref="OpenArrow.Templating.ActionResults"/>
    /// </summary>
    public class IndividualProcessorResults : ActionResults
    {
        #region Private Fields

        private TemplateParserResults parserResults;
        private TemplateGeneratorResults generatorResults;
        private TemplateCompilerResults compilerResults;
        private bool rebuildProblems = true;

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the results of the parsing phase of template processing
        /// </summary>
        public TemplateParserResults ParserResults
        {
            get { return parserResults; }
            set { parserResults = value; rebuildProblems = true; }
        }

        /// <summary>
        /// Gets or sets the results of the generation phase of template processing
        /// </summary>
        public TemplateGeneratorResults GeneratorResults
        {
            get { return generatorResults; }
            set { generatorResults = value; rebuildProblems = true; }
        }

        /// <summary>
        /// Gets or sets the results of the compilation phase of template processing
        /// </summary>
        public TemplateCompilerResults CompilerResults
        {
            get { return compilerResults; }
            set { compilerResults = value; rebuildProblems = true; }
        }

        /// <summary>
        /// Gets a collection of errors and warnings (generically: problems) that occurred
        /// during the action.
        /// <seealso cref="ActionResults.Problems"/>
        /// </summary>
        public override ProblemCollection Problems
        {
            get
            {
                if (rebuildProblems)
                {
                    base.Problems.Clear();
                    if (this.ParserResults != null)
                        base.Problems.AddRange(this.ParserResults.Problems);
                    if (this.GeneratorResults != null)
                        base.Problems.AddRange(this.GeneratorResults.Problems);
                    if (this.CompilerResults != null)
                        base.Problems.AddRange(this.CompilerResults.Problems);
                    rebuildProblems = false;
                }
                return base.Problems;
            }
        }

        /// <summary>
        /// Gets or sets a boolean determining if the action was successful
        /// <seealso cref="ActionResults.Success"/>
        /// </summary>
        public override bool Success
        {
            get
            {
                bool ps = true;
                if (this.ParserResults != null)
                    ps = this.ParserResults.Success;
                bool gs = true;
                if (this.GeneratorResults != null)
                    gs = this.GeneratorResults.Success;
                bool cs = true;
                if (this.CompilerResults != null)
                    cs = this.CompilerResults.Success;
                return ps && gs && cs;
            }
            set { /* HACK: Shouldn't just silently fail, but because ActionResults.ctor calls sets this, we don't have much choice */ }
        } 

        #endregion

        #region Public Constructors

        /// <summary>
        /// Constructs a new <see cref="IndividualProcessorResults"/> object
        /// </summary>
        public IndividualProcessorResults() { }

        /// <summary>
        /// Constructs a new <see cref="IndividualProcessorResults"/> object
        /// </summary>
        /// <param name="parserResults">The results of parsing template files</param>
        /// <param name="generatorResults">The results of generating source code from parsed templates</param>
        /// <param name="compilerResults">The results of compiling the source code</param>
        /// <exception cref="ArgumentNullException"><paramref name="parserResults"/> is <see langword="null"/></exception>
        /// <exception cref="ArgumentNullException"><paramref name="generatorResults"/> is <see langword="null"/></exception>
        /// <exception cref="ArgumentNullException"><paramref name="compilerResults"/> is <see langword="null"/></exception>
        public IndividualProcessorResults(TemplateParserResults parserResults, TemplateGeneratorResults generatorResults,
            TemplateCompilerResults compilerResults)
        {
            if (parserResults == null)
                throw new ArgumentNullException(String.Format(Resources.Exception_ArgIsNull, "parserResults"), "parserResults");
            if (generatorResults == null)
                throw new ArgumentNullException(String.Format(Resources.Exception_ArgIsNull, "generatorResults"), "generatorResults");
            if (compilerResults == null)
                throw new ArgumentNullException(String.Format(Resources.Exception_ArgIsNull, "compilerResults"), "compilerResults");

            this.parserResults = parserResults;
            this.generatorResults = generatorResults;
            this.compilerResults = compilerResults;
        } 

        #endregion
    }
}
